import 'package:todos_app_core/todos_app_core.dart';
import 'package:todos_repository_core/todos_repository_core.dart';

class AppState {
  bool isLoading;
  List<Todo> todos;

  AppState({this.isLoading = false, this.todos = const []});
  factory AppState.loading() => AppState(isLoading: true);
  bool get allComplete => todos.every((todo) => todo.complete);
  bool get hasCompletedTodos => todos.any((todo) => todo.complete);

  int get numActive =>
      todos.fold(0, (sum, todo) => !todo.complete ? ++sum : sum);

  int get numCompleted =>
      todos.fold(0, (sum, todo) => todo.complete ? ++sum : sum);
  List<Todo> filterTodos(VisibilityFilter filter) => todos.where((todo) {
        switch (filter) {
          case VisibilityFilter.active:
            return !todo.complete;
          case VisibilityFilter.completed:
            return todo.complete;
          case VisibilityFilter.all:
          default:
            return true;
        }
      }).toList();

  void toggleAll() {
    final allComleted = allComplete;
    todos.forEach((todo) => todo.complete = !allComleted);
  }

  void clearCompleted() {
    todos.removeWhere((todo) => todo.complete);
  }

  void inverseCompleted() {
    todos.forEach((todo) => todo.complete = !todo.complete);
  }
}

class Todo {
  bool complete;
  String id;
  String note;
  String task;

  Todo(this.task, {this.complete = false, String? id, this.note = ''})
      : id = id ?? Uuid().generateV4();

  //override hashCode and == operator to compare two objects
  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Todo &&
          runtimeType == other.runtimeType &&
          id == other.id &&
          complete == other.complete &&
          task == other.task &&
          note == other.note;

  @override
  int get hashCode =>
      id.hashCode ^ complete.hashCode ^ task.hashCode ^ note.hashCode;

  //override toString method to print object in a readable format
  @override
  String toString() {
    return 'Todo{id: $id, complete: $complete, task: $task, note: $note}';
  }

  //toEntity method to convert object to entity
  TodoEntity toEntity() {
    return TodoEntity(task, id, note, complete);
  }

  static Todo fromEntity(TodoEntity entity) {
    return Todo(entity.task,
        id: entity.id ?? Uuid().generateV4(),
        note: entity.note,
        complete: entity.complete);
  }
}

enum AppTab { todos, stats }

enum ExtraAction { toggleAllComplete, clearCompleted, inverseCompleted }

enum VisibilityFilter { all, active, completed }
